package edu.fau.scanny.r.stromal.servlet;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanToPropertyValueTransformer;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.rosuda.REngine.REXPMismatchException;
import org.rosuda.REngine.REngineException;
import org.rosuda.REngine.Rserve.RConnection;

import edu.fau.scanny.r.RBioconductorUtils;
import edu.fau.scanny.r.RUtils;
import edu.fau.scanny.r.StartRserve;
import edu.fau.scanny.r.stromal.RStromalFactory;
import edu.fau.scanny.r.stromal.RStromalPlotFactory;
import edu.fau.scanny.r.stromal.model.CelFile;
import edu.fau.scanny.r.stromal.model.GroupOutput;
import edu.fau.scanny.r.stromal.model.IdTable;
import edu.fau.scanny.r.stromal.model.StromalCalculatorModel;
import edu.fau.scanny.stromal.MetaFileUtils;

public class StromalCalcIntroServlet extends HttpServlet {

	public static Map<String, Map<String, String>> groupNameFileMap = null;
	private static Map<String, CelFile> chipCelFileMap = null;
	private static String celFileLocation;
	private static String servletPath;
	private static IdTable idTable;

	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		String fName = config.getServletContext().getRealPath(GlobalVariables.META_FILE);
		System.out.println("RServe started " + StartRserve.checkLocalRserve());

		try {
			chipCelFileMap = MetaFileUtils.chipCelFileMap(fName);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		celFileLocation = config.getInitParameter("celFileLocation");
		servletPath = StringUtils.replace(config.getServletContext().getRealPath("index.jsp"), "index.jsp", "");

		// mouse information
		idTable = StromalCalculatorUtils.setUpIdTable(config);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGet(req, resp);
	}

	public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

		// parameters from form
		List<String> chips = Arrays.asList(req.getParameterValues("chips"));
		StromalCalculatorModel model = StromalCalculatorUtils.setUpStromalCalculatorModel(chips, chipCelFileMap, req.getParameter("normalization"),
				StromalCalculatorUtils.getBoolParam(req, "logLinear", "log"));

		// check if both whole tissue and lymphoid has been selected
		for (Entry<String, Map<String, List<CelFile>>> entry : model.getGroupFilesMap().entrySet()) {
			if (entry.getValue().size() < 2){
				req.setAttribute("error", String.format("%s does not have both a whole tissue and lymphocyte CEL file selected.", entry.getKey()));
				req.getRequestDispatcher("error.jsp").forward(req, resp);
				return;
			}
		}

		// make sure rserve is running
		System.out.println("result=" + StartRserve.checkLocalRserve());
		RConnection rc = null;
		try {

			rc = new RConnection();
			// RUtils.loadWorkSpace(rc, workspaceFile);

			String normDataVar = GlobalVariables.NORM_DATA;
			String sampleDataVar = GlobalVariables.SAMPLES;

			RUtils.assign(rc, RUtils.readTable(idTable.getTableFile(), true, "1", "\\t", true), idTable.getrTableVar());

			RUtils.loadLibrary(rc, "simpleaffy");
			
			File normFile = RStromalFactory.normalizeFile(rc, celFileLocation, model, sampleDataVar, normDataVar, idTable);
			File boxPlot = File.createTempFile(model.getNormalizationMethod() + "_" + normDataVar + "_boxplot_", ".png", new File(servletPath));
			boxPlot.deleteOnExit();

			BeanToPropertyValueTransformer transformer = new BeanToPropertyValueTransformer("shortName");
			List<String> shortNames = (List<String>) CollectionUtils.collect(model.getCelFiles(), transformer);
			RStromalPlotFactory.boxPlot(rc, boxPlot, normDataVar, true, model.getNormalizationMethod() + " Signals", shortNames,
					"Selected Samples Normalized Signal Ranges", true);

			RBioconductorUtils.preprocessCoreLibrary(rc);
			RUtils.pracmaLibrary(rc);

			String rorPlot = "rankOrderedRatioPlot";
			String pTan = "plymphTangent";
			String pPer = "plymphPerpendicular";
			String pLymphSp = "plymphLymphSpecific";
			String presentCallVar = "PercentPresentWholeTissue";

			Map<String, GroupOutput> groupOutputs = new LinkedHashMap<String, GroupOutput>();
			List<String> wholePartVarNames = new ArrayList<String>();

			String lymphSpecific = "lymphSpecific";
			StromalCalculatorUtils.asCharacterReadInFile(this, rc, lymphSpecific, "subtract_specific", false, "NULL", true);
			for (Entry<String, Map<String, List<CelFile>>> entry : model.getGroupFilesMap().entrySet()) {
				Map<String, List<CelFile>> filesMap = entry.getValue();
				String timeGroupVar = StringUtils.replace(entry.getKey(), " ", "");
				wholePartVarNames.add(timeGroupVar);

				String presentCallVarIndv = presentCallVar + "." + entry.getKey().replace(" ", "");

				File ratioFile = File.createTempFile(timeGroupVar + "_ratio_", ".png", new File(servletPath));
				ratioFile.deleteOnExit();

				// Main Process
				GroupOutput go = RStromalFactory.processGroup(rc, ratioFile, Arrays.asList(new String[] { "Tissue", "Lymphoid Cells" }),
						entry.getKey(), filesMap, "Tissue", presentCallVarIndv, normDataVar, sampleDataVar, rorPlot, pPer, pTan, pLymphSp,
						timeGroupVar, lymphSpecific);

				groupOutputs.put(entry.getKey(), go);
			}


			req.setAttribute("groupMap", model.getGroupFilesMap());
			req.setAttribute("groupOutputs", groupOutputs);
			File workspaceFile = RUtils.saveWorkspace(rc);

			req.setAttribute("log2", model.isLog2());
			req.setAttribute("normalization", model.getNormalizationMethod().toString());
			req.setAttribute("wholePartVar", StringUtils.join(wholePartVarNames, ","));
			req.setAttribute("normFile", normFile.getAbsolutePath());
			req.setAttribute("boxplot", boxPlot.getName());
			req.setAttribute("workspaceFile", workspaceFile.getAbsolutePath().replace("\\", "/"));

			rc.close();
			req.getRequestDispatcher("plymphoid.jsp").forward(req, resp);

		} catch (REngineException ex) {
			rc.close();
			StromalCalculatorUtils.errorHandling(ex, req, resp);
		} catch (REXPMismatchException ex) {
			rc.close();
			StromalCalculatorUtils.errorHandling(ex, req, resp);
		}
	}

	

}
